#pragma once
#include "Reflectable.h"
#include "Marshal.h"

/* Extern imported global functions from 'libnc' */
int NcCreate(const char* library, const char* type, void** reflectable);
int NcGetCachedObject(const char* library, const char* type, void** reflectable, int objectId = 0);
int NcRegister(const char* library, noria::RegisterCallback callback);

namespace noria {

	class IMarshal;
	template<typename T = void*>
	class ActivatorT final
	{
	public:
		static void RegisterTypes(const char* library, RegisterCallback callback)
		{
			NcRegister(library, callback);
		}
		static IReflectable* CreateInstance(const char* library, const char* type)
		{
			IReflectable* ptr;
			auto hr = NcCreate(library, type, reinterpret_cast<void**>(&ptr));
			if (hr != 0)
			{
				throw runtime_error("cannot create type");
			}
			return ptr;
		}
		static inline const IReflectable& GetStaticInstance(const char* library, const char* type)
		{
			return GetSingletonInstance(library, type);
		}
		static inline IReflectable& GetSingletonInstance(const char* library, const char* type)
		{
			IReflectable* ptr;
			auto hr = NcGetCachedObject(library, type, reinterpret_cast<void**>(&ptr));
			if (hr != 0)
			{
				throw runtime_error("cannot get cached object");
			}
			return *ptr;
		}
		// system objects
		static inline const IMarshal& GetMarshal()
		{
			IMarshal* ptr;
			NcGetCachedObject(nullptr, nullptr, reinterpret_cast<void**>(&ptr), SystemObject::_Marshal);
			return *ptr;
		}
	};
	typedef ActivatorT<> Activator;



#define AcMarshal __marshal
#ifdef NCLIB_MAIN
	const IMarshal& AcMarshal = static_cast<const IMarshal&>(Activator::GetStaticInstance("libnc", "noria.Marshal"));
#else
	extern const IMarshal& AcMarshal;
#endif

}